﻿using AdBlockListToTPLConverter;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Collections.Generic;
using System.Linq;

namespace ConverterTests
{


    /// <summary>
    ///This is a test class for AdBlockConverterTest and is intended
    ///to contain all AdBlockConverterTest Unit Tests
    ///</summary>
    [TestClass()]
    public class AdBlockConverterTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {

        }
        //
        //Use ClassCleanup to run code after all tests in a class have run
        [ClassCleanup()]
        public static void MyClassCleanup()
        {

        }
        //

        //Use TestInitialize to run code before running each test
        [TestInitialize()]
        public void MyTestInitialize()
        {
            _input = new MemoryStream();
            _inputWriter = new StreamWriter(_input);

            _output = new MemoryStream();
            _outputReader = new StreamReader(_output);
        }

        //Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup()
        {
            _inputWriter.Close();
            _input.Close();
            _inputWriter = null;
            _input = null;

            _outputReader.Close();
            _output.Close();
            _output = null;
            _outputReader = null;


        }

        #endregion

        MemoryStream _input;
        MemoryStream _output;

        StreamWriter _inputWriter;
        StreamReader _outputReader;

        [TestMethod()]
        public void StandardRulesConvertTest()
        {
            string[] input = 
            {
                "&ad_keyword=",
                "&ad_type_",
                "&adname=",
                "&adspace=",
                "-third-ad.",
                ".org/ad/",
                "_small_ad.",
                "=300x250"
            };

            string[] expectedOutput = 
            {
                "msFilterList",
                "- &ad_keyword=",
                "- &ad_type_",
                "- &adname=",
                "- &adspace=",
                "- -third-ad.",
                "- .org/ad/",
                "- _small_ad.",
                "- =300x250"
            };

            IList<string> output = TestConvert(input);

            Assert.AreEqual(expectedOutput[0], output[0]);
            CollectionAssert.AreEquivalent(expectedOutput.Skip(1).ToArray(), output.Skip(1).ToList());
        }

        [TestMethod()]
        public void SpecialCharactersRulesConvertTest()
        {
            string[] input = 
            {
                "[Adblock Plus]",
                "||onet.pl/_s/kropka/*$domain=~poczta.onet.pl",
                "http://*.openx.net/*"
            };

            string[] expectedOutput = 
            {
                "msFilterList",
                "- onet.pl/_s/kropka/*",
                "- http://*.openx.net/*"
            };

            IList<string> output = TestConvert(input);

            Assert.AreEqual(expectedOutput[0], output[0]);
            CollectionAssert.AreEquivalent(expectedOutput.Skip(1).ToArray(), output.Skip(1).ToList());
        }

        [TestMethod()]
        public void SeparatorCharacterConvertTest1()
        {
            string[] input = 
            {
                "||ibnlive.in.com^*/ibn_*_banner_",
                "||ibtimes.com/banner/"
            };

            string[] expectedOutput = 
            {                
                "msFilterList",
                "- ibnlive.in.com:*/ibn_*_banner_",
                "- ibnlive.in.com/*/ibn_*_banner_",
                "- ibnlive.in.com?*/ibn_*_banner_",
                "- ibnlive.in.com=*/ibn_*_banner_",
                "- ibnlive.in.com&*/ibn_*_banner_",                
                "- ibtimes.com/banner/"
            };

            IList<string> output = TestConvert(input);

            Assert.AreEqual(expectedOutput[0], output[0]);
            CollectionAssert.AreEquivalent(expectedOutput.Skip(1).ToArray(), output.Skip(1).ToList());
        }

        [TestMethod()]
        public void SeparatorCharacterConvertTest2()
        {
            string[] input = 
            {
                "||quickload.to^*/blase.js",  
                "||tradedoubler.com^$third-party",
                "^example^"
            };

            string[] expectedOutput = 
            {                
                "msFilterList",
                "- quickload.to:*/blase.js",
                "- quickload.to/*/blase.js",
                "- quickload.to?*/blase.js",
                "- quickload.to=*/blase.js",
                "- quickload.to&*/blase.js",
                "- tradedoubler.com",
                "- :example",
                "- /example",
                "- ?example",
                "- =example",
                "- &example"                
            };

            IList<string> output = TestConvert(input);

            Assert.AreEqual(expectedOutput[0], output[0]);
            CollectionAssert.AreEquivalent(expectedOutput.Skip(1).ToArray(), output.Skip(1).ToList());
        }

        [TestMethod()]
        public void SeparatorCharacterConvertTest3()
        {
            string[] input = 
            {                
                "^foo^bar^"
            };            
            string[] expectedOutput = 
            {                
                "msFilterList",
                "- :foo:bar",
                "- :foo/bar",
                "- :foo?bar",
                "- :foo=bar",
                "- :foo&bar",
                "- /foo:bar",
                "- /foo/bar",
                "- /foo?bar",
                "- /foo=bar",
                "- /foo&bar",
                "- ?foo:bar",
                "- ?foo/bar",
                "- ?foo?bar",
                "- ?foo=bar",
                "- ?foo&bar",
                "- =foo:bar",
                "- =foo/bar",
                "- =foo?bar",
                "- =foo=bar",
                "- =foo&bar",
                "- &foo:bar",
                "- &foo/bar",
                "- &foo?bar",
                "- &foo=bar",
                "- &foo&bar"
            };

            IList<string> output = TestConvert(input);

            Assert.AreEqual(expectedOutput[0], output[0]);
            CollectionAssert.AreEquivalent(expectedOutput.Skip(1).ToArray(), output.Skip(1).ToList());
        }

        [TestMethod()]
        public void ExceptionRulesConvertTest()
        {
            string[] input = 
            {
                "[Adblock Plus]",  
                "@@|http://x.interia.pl/cintpl/*",
                "@@|http://x.interia.pl/inpl/inpl.ad.comp$script,domain=video.interia.pl",
                "@@|http://x.interia.pl/inpl/inpl.intad$script,domain=video.interia.pl",
                "@@||reklama.onet.pl/_js/*"
            };

            string[] expectedOutput = 
            {                
                "msFilterList",
                "+ http://x.interia.pl/cintpl/*",
                "+ http://x.interia.pl/inpl/inpl.ad.comp",
                "+ http://x.interia.pl/inpl/inpl.intad",             
                "+ reklama.onet.pl/_js/*"
            };

            IList<string> output = TestConvert(input);

            Assert.AreEqual(expectedOutput[0], output[0]);
            CollectionAssert.AreEquivalent(expectedOutput.Skip(1).ToArray(), output.Skip(1).ToList());
        }


        [TestMethod()]
        public void BeginningEndingMatchingConvertTest()
        {
            string[] input = 
            {
                "@@|http://x.interia.pl/cintpl/*",  
                "@@||reklama.onet.pl/_js/*",
                "||themes420.com/bnrsbtns/",
                "?goto=ad|",
                "||mmo4rpg.com^*.gif|$third-party"
            };

            string[] expectedOutput = 
            {                
                //{ ':', '/', '?', '=', '&' };
                "msFilterList",
                "+ http://x.interia.pl/cintpl/*",  
                "+ reklama.onet.pl/_js/*",
                "- themes420.com/bnrsbtns/",
                "- ?goto=ad",
                "- mmo4rpg.com:*.gif",
                "- mmo4rpg.com/*.gif",
                "- mmo4rpg.com?*.gif",
                "- mmo4rpg.com=*.gif",
                "- mmo4rpg.com&*.gif"
            };

            IList<string> output = TestConvert(input);

            Assert.AreEqual(expectedOutput[0], output[0]);
            CollectionAssert.AreEquivalent(expectedOutput.Skip(1).ToArray(), output.Skip(1).ToList());
        }





        private IList<string> TestConvert(string[] adblockFilterRules)
        {


            writeArrayToInput(adblockFilterRules);

            AdBlockConverter.Convert(_input, _output);

            return getListFromOutput();
        }

        private void writeArrayToInput(IList<string> list)
        {
            foreach (var element in list)
            {
                _inputWriter.WriteLine(element);
            }
            _inputWriter.Flush();
            _input.Position = 0;
        }

        private IList<string> getListFromOutput()
        {
            List<string> list = new List<string>();
            _output.Position = 0;

            string line;
            while ((line = _outputReader.ReadLine()) != null)
            {
                list.Add(line);
            }
            return list;
        }

    }
}
